//策略模式定义了一系列的算法，把它们一个个封装起来，并且使他们可以相互替换。策略模式的重心不是如何实现算法，
//而是如何组织、调用这些算法，从而让程序结构更灵活、可维护、可扩展。

interface Strategy {
  authenticate(...args: any): any;
}

class Authenticator {
  stragegy: any;
  constructor() {
    this.stragegy = null;
  }

  setStrategy(strategy: any) {
    this.stragegy = strategy;
  }

  authenticate(...args: any) {
    if (!this.stragegy) {
      console.log("尚未设置认证策略");
      return;
    }
    return this.stragegy.authenticate(...args);
  }
}

class WechatStragegy implements Strategy {
  authenticate(wechatToken: string) {
    if (wechatToken !== "123") {
      console.log("无效的微信用户");
      return;
    }
    console.log("微信认证成功");
  }
}

class LocalStrategy implements Strategy {
  authenticate(username: string, password: string) {
    if (username !== "abao" && password !== "123") {
      console.log("账号或密码错误");
      return;
    }
    console.log("账号或密码认证成功");
  }
}

const auth = new Authenticator();

auth.setStrategy(new WechatStragegy());
auth.authenticate("123456");

auth.setStrategy(new LocalStrategy());
auth.authenticate("abao", "123");

//应用场景
//1.一个系统需要动态地在集中算法中选择一种时，可将每个算法封装到策略类中
//2.多个类只区别在表现行为不同，可以使用策略模式，在运行时动态选择具体要执行的行为。
//3.一个类定义了多种行为，并且这些行为在这个类的操作中以多个条件语句的形式出现，可将每个
//  条件分支移入他们各自的策略类中以代替这些条件语句
